package com.jtw.sys.service.user;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.jtw.common.bean.enums.ReqCode;
import com.jtw.common.bean.vo.FindPagingVo;
import com.jtw.common.bean.vo.FindParamVo;
import com.jtw.common.bean.vo.PagingVo;
import com.jtw.common.org.Sid;
import com.jtw.common.util.HttpUtil;
import com.jtw.common.util.MD5;
import com.jtw.common.util.PagingUtil;
import com.jtw.common.util.RandomUtil;
import com.jtw.conf.shiro.model.BaseUser;
import com.jtw.conf.shiro.util.PasswordUtil;
import com.jtw.conf.shiro.util.ShiroUtil;
import com.jtw.sys.constants.Constant;
import com.jtw.sys.emuns.AssetChangeCode;
import com.jtw.sys.mapper.member.*;
import com.jtw.sys.mapper.perm.PermMapper;
import com.jtw.sys.mapper.user.SysRoleMapper;
import com.jtw.sys.mapper.user.SysUserInfoMapper;
import com.jtw.sys.mapper.user.SysUserMapper;
import com.jtw.sys.mapper.user.SysUserOpenMapper;
import com.jtw.sys.model.member.*;
import com.jtw.sys.model.user.TSysRole;
import com.jtw.sys.model.user.TSysUser;
import com.jtw.sys.model.user.TSysUserInfo;
import com.jtw.sys.model.user.TSysUserOpen;
import com.jtw.sys.vo.member.*;
import com.jtw.sys.vo.role.SysRoleUpdateVo;
import com.jtw.sys.vo.user.SysUserAccountPermVo;
import com.jtw.sys.vo.user.SysUserAddReq;
import com.jtw.sys.vo.user.SysUserInfoBaseVo;
import com.jtw.sys.vo.user.UserWithdrawPwdResetVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.bouncycastle.cert.ocsp.Req;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * DESCRIPT:
 *
 * @author cjsky666
 * @date 2018-8-24 14:27
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    public static final String WhereIsAdminSql =" AND `t_sys_user`.`ID` IN (SELECT * FROM `ct_sys_user_admin`) ";
    @Autowired
    private Sid sid;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserInfoMapper sysUserInfoMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private MemberPwdResetMapper memberPwdResetMapper;
    @Autowired
    private MemberCheckInMapper memberCheckInMapper;
    @Autowired
    private MemberCheckInRewardMapper memberCheckInRewardMapper;
    @Autowired
    private MemberAssetMapper memberAssetMapper;
    @Autowired
    private MemberAssetLogMapper memberAssetLogMapper;
    @Autowired
    private PermMapper permMapper;
    @Autowired
    private SysUserOpenMapper sysUserOpenMapper;


//    @CachePut(value = "2m", key = "'com.jtw.sys.service.user.save'+#sysUser.id")
    public void save(TSysUser sysUser) {
        sysUserMapper.insert(sysUser);
    }

    @Override
    public void saveAll(List<TSysUser> list) {
        sysUserMapper.insertList(list);
    }

    public void update(TSysUser sysUser) {
        sysUserMapper.updateByPrimaryKeySelective(sysUser);
    }

    @Override
    public void delete(Object id) {
        sysUserMapper.deleteByPrimaryKey(id);
    }




    @Override
    public Page<TSysUser> findAll(PagingVo pagingVo) {
        PagingUtil.start(pagingVo);
        return sysUserMapper.findAll(pagingVo);
    }

    @Override
    public Page<TSysUser> findAll(FindPagingVo findPagingVo) {
        return null;
    }

    @Override
    public List<TSysUser> getAll() {
        return null;
    }

//    @Cacheable(value = "2m", key = "'com.jtw.sys.service.user.save'+#id")
    public TSysUser getById(Object id) {
        return sysUserMapper.selectByPrimaryKey(id);
    }

    public Page<TSysUser> queryList(PagingVo pagingVo) {
        PagingUtil.start(pagingVo);
        return sysUserMapper.findAll(pagingVo);
    }

    @Override
    public SysUserInfoBaseVo getUserInfoBaseVoByUserName(String userName) {
        SysUserInfoBaseVo sysUserInfoBaseVo = sysUserMapper.getUserInfoBaseVoByUserName(userName);
        if (sysUserInfoBaseVo == null) {
            throw ReqCode.UnExistingSysUser.getException();
        }
        return sysUserInfoBaseVo;
    }

    public Page<SysUserInfoBaseVo> findAllUserInfoBaseVo(FindPagingVo findPagingVo) {
        PagingUtil.start(findPagingVo);
        return sysUserMapper.findAllUserInfoBaseVo(PagingUtil.buildWhereSQLToString(findPagingVo.getFindParams()));
    }

    @Override
    public void updateUserLoginTime(Long id) {
        sysUserMapper.updateUserLoginTime(id,new Date());
    }

    @Override
    @Transactional
    public void addSysUserAccount(SysUserAddReq sysUserAddReq, HttpServletRequest request) {
        if(sysUserMapper.isExistsWithUserName(sysUserAddReq.getUserName())){
            throw ReqCode.SysUserNameisExist.getException();
        }

        String ip = request.getRemoteAddr();
        String operator = "";
        if(request.getSession().getAttribute(Constant.KEY_USER_USER_NAME)!=null){
            operator = (String) request.getSession().getAttribute(Constant.KEY_USER_USER_NAME);
        }else{
            operator = sysUserAddReq.getUserName();
        }

        TSysUser sysUser = new TSysUser();
        BeanUtils.copyProperties(sysUserAddReq,sysUser);
        sysUser.setOperator(operator);
        sysUser.setOperatorIp(ip);
        sysUser.setSalt(PasswordUtil.getSalt());
        sysUser.setPassword(PasswordUtil.encryptPassword(sysUserAddReq.getPassword(),sysUser.getSalt()));
        //新建默认用户信息
        sysUserMapper.insertSelective(sysUser);

        //新建默认用户基本信息
        TSysUserInfo userInfo = new TSysUserInfo();
        userInfo.setId(sysUser.getId());
        userInfo.setOperator(operator);
        if (StringUtils.isNotBlank(sysUserAddReq.getNickName())){
            userInfo.setNickName(sysUserAddReq.getNickName());
        }else{
            userInfo.setNickName(sid.nextShort());//随机给一个昵称
        }


        userInfo.setOperatorIp(ip);
        sysUserInfoMapper.insertSelective(userInfo);

        TSysMemberAsset memberAsset = new TSysMemberAsset();
        memberAsset.setBalance(1000);
        memberAsset.setFreezeBalance(0);
        memberAsset.setId(userInfo.getId());
        if(memberAssetMapper.insertSelective(memberAsset)!=1){
            throw ReqCode.UnKnowException.getException();
        }
        TSysMemberAssetLog log = new TSysMemberAssetLog();
        log.setUserId(userInfo.getId());
        log.setSerialNo(sid.nextShort());
        log.setOperatorIp(request.getRemoteAddr());
        log.setOperator(sysUser.getUserName());
        log.setBalance(1000);
        log.setType(AssetChangeCode.ADD_CREATE.getType());
        log.setDescript(AssetChangeCode.ADD_CREATE.getDescript());
        log.setAssetFreezeBalance(memberAsset.getFreezeBalance());
        log.setAssetBalance(memberAsset.getBalance());
        log.setCreateTime(LocalDateTime.now().toDate());
        memberAssetLogMapper.insertSelective(log);


        //新建用户默认角色信息--用户角色
        sysUserMapper.insertUserRolesByUserId(sysUser.getId(),new Integer[]{Constant.ROLE_ID_MEMBER},operator,ip);

    }

    @Override
    public void lockedSysUserAccount(Long userId) {
        if(userId.equals(Constant.USER_ID_SUPER_ADMIN)){
            throw ReqCode.NoPermission.getException();
        }
        if(sysUserMapper.existsWithPrimaryKey(userId)){
            TSysUser sysUser = new TSysUser();
            sysUser.setId(userId);
            sysUser.setState(1);
            sysUserMapper.updateByPrimaryKeySelective(sysUser);
        }else{
           throw ReqCode.UnExistingSysUser.getException();
        }
    }

    @Override
    public void unlockedSysUserAccount(Long userId) {
        if(sysUserMapper.existsWithPrimaryKey(userId)){
            TSysUser sysUser = new TSysUser();
            sysUser.setId(userId);
            sysUser.setState(0);
            sysUserMapper.updateByPrimaryKeySelective(sysUser);
        }else{
            throw ReqCode.UnExistingSysUser.getException();
        }
    }

    @Override
    @Transactional
    public void modifyUserRolesByUserId(Long id, Integer[] roleList,HttpServletRequest request) {
        for(Integer roleId : roleList){
            if(!sysRoleMapper.existsWithPrimaryKey(roleId)){
                throw ReqCode.UnExistingSysRole.getException("ID为"+roleId+"的角色不存在");
            }
        }
        sysUserMapper.delUserRolesByUserId(id);
        if(roleList.length>0){
            sysUserMapper.insertUserRolesByUserId(id,roleList, (String) request.getSession().getAttribute(Constant.KEY_USER_USER_NAME),request.getRemoteAddr());
        }
    }

    @Override
    public void modifySysUserBaseInfoByUserId(TSysUserInfo sysUserInfo) {
        if(sysUserInfoMapper.existsWithPrimaryKey(sysUserInfo.getId())){
            sysUserInfoMapper.updateByPrimaryKeySelective(sysUserInfo);
        }else{
            throw ReqCode.UnExistingSysUser.getException();
        }
    }

    @Override
    public List<SysRoleUpdateVo> getUserRolesByUserId(Long userId) {
        return sysUserMapper.getUserRolesByUserId(userId);
    }

    @Override
    public List<SysRoleUpdateVo> getAllRolesByUserIdNotHave(Long userId) {
        return sysUserMapper.getAllRolesByUserIdNotHave(userId);
    }

    @Override
    public List<SysUserAccountPermVo> getAllPermsBySysUserId(Long userId) {
        return sysUserMapper.getAllPermsBySysUserId(userId);
    }

    @Override
    public void modifyAccountPwdByUserId(Long userId, String newPassword) {
        if(userId.equals(Constant.USER_ID_SUPER_ADMIN)&&!userId.equals(Long.valueOf(SecurityUtils.getSubject().getSession().getAttribute(Constant.USER_PRIMARY_KEY).toString()))){
            throw ReqCode.NoPermission.getException();
        }
        TSysUser sysUser = new TSysUser();
        sysUser.setId(userId);
        sysUser.setSalt(PasswordUtil.getSalt());
        sysUser.setPassword(PasswordUtil.encryptPassword(newPassword,sysUser.getSalt()));
        sysUserMapper.updateByPrimaryKeySelective(sysUser);
    }

    @Override
    public Boolean isAdmin(Long userId) {
        return sysUserMapper.isAdmin(userId);
    }

    @Override
    public Page<SysUserInfoBaseVo> findAllAdminUserInfoBaseVo(FindPagingVo findPagingVo) {
        PagingUtil.start(findPagingVo);
        return sysUserMapper.findAllUserInfoBaseVo(PagingUtil.buildCustomeWhereSQLToString(WhereIsAdminSql,findPagingVo.getFindParams()));
    }

    @Override
    public void modifyMemberPwd(HttpServletRequest request, MemberPwdReq memberPwdReq) {
        TSysUser sysUser = sysUserMapper.selectByPrimaryKey((Long) request.getSession().getAttribute(Constant.USER_PRIMARY_KEY));
        if(sysUser==null){
            throw ReqCode.UnExistingSysUser.getException();
        }
        if(!sysUser.getPassword().equals(PasswordUtil.encryptPassword(memberPwdReq.getOldPassword(),sysUser.getSalt()))){
            throw ReqCode.MemberOldPasswordIsInvalid.getException();
        }
        sysUser.setSalt(PasswordUtil.getSalt());
        sysUser.setPassword(PasswordUtil.encryptPassword(memberPwdReq.getPassword(),sysUser.getSalt()));
        sysUser.setOperator((String) request.getSession().getAttribute(Constant.KEY_USER_USER_NAME));
        sysUser.setOperatorIp(request.getRemoteAddr());
        sysUser.setCreateTime(null);
        sysUser.setUpdateTime(null);
        sysUserMapper.updateByPrimaryKeySelective(sysUser);
    }


    @Override
    public void MemberPwdResetReq(HttpServletRequest request, MemberPwdResetReq memberPwdResetReq) {
        TSysMemberPwdReset tSysMemberPwdReset =memberPwdResetMapper.getOneByUserName(request.getSession().getAttribute(Constant.KEY_USER_USER_NAME));
        if(tSysMemberPwdReset!=null){
            throw ReqCode.MemberPwdApplyIsExistIng.getException();
        }
        tSysMemberPwdReset = new TSysMemberPwdReset();
        BeanUtils.copyProperties(memberPwdResetReq,tSysMemberPwdReset);
        tSysMemberPwdReset.setUserName((String) request.getSession().getAttribute(Constant.KEY_USER_USER_NAME));
        tSysMemberPwdReset.setOperator(tSysMemberPwdReset.getUserName());
        tSysMemberPwdReset.setOperatorIp(request.getRemoteAddr());
        tSysMemberPwdReset.setState(0);
        memberPwdResetMapper.insertSelective(tSysMemberPwdReset);
    }

    @Override
    public Page<UserWithdrawPwdResetVo> findAllPwdResetApply(FindPagingVo findPagingVo) {
        PagingUtil.start(findPagingVo);
        return sysUserMapper.findAllPwdResetApply(PagingUtil.buildWhereSQLToString(findPagingVo.getFindParams()));
    }



    @Override
    public void confirmPwdResetApply(HttpServletRequest request, Long id) {
        TSysMemberPwdReset tSysMemberPwdReset = memberPwdResetMapper.selectByPrimaryKey(id);
        if(tSysMemberPwdReset.getState()!=0){
            throw ReqCode.DataProcessERROR.getException();
        }
        //更新用户的登陆密码
        SysUserInfoBaseVo userInfoBaseVoByUserName = sysUserMapper.getUserInfoBaseVoByUserName(tSysMemberPwdReset.getUserName());
        TSysUser sysUser = new TSysUser();
        sysUser.setId(userInfoBaseVoByUserName.getId());
        sysUser.setSalt(PasswordUtil.getSalt());
        sysUser.setPassword(PasswordUtil.encryptPassword(tSysMemberPwdReset.getPassword(),sysUser.getSalt()));
        sysUserMapper.updateByPrimaryKeySelective(sysUser);
        //更新登陆密码重置申请记录
        tSysMemberPwdReset.setOperator((String) request.getSession().getAttribute(Constant.KEY_USER_USER_NAME));
        tSysMemberPwdReset.setOperatorIp(request.getRemoteAddr());
        tSysMemberPwdReset.setUpdateTime(null);
        tSysMemberPwdReset.setState(1);
        tSysMemberPwdReset.setDescript("已处理");
        memberPwdResetMapper.updateByPrimaryKeySelective(tSysMemberPwdReset);
    }

    @Override
    public void refusedPwdResetApply(HttpServletRequest request, Long id,String reason) {
        TSysMemberPwdReset tSysMemberPwdReset = memberPwdResetMapper.selectByPrimaryKey(id);
        if(tSysMemberPwdReset.getState()!=0){
            throw ReqCode.DataProcessERROR.getException();
        }
        tSysMemberPwdReset.setOperator((String) request.getSession().getAttribute(Constant.KEY_USER_USER_NAME));
        tSysMemberPwdReset.setOperatorIp(request.getRemoteAddr());
        tSysMemberPwdReset.setUpdateTime(null);
        tSysMemberPwdReset.setState(2);
        tSysMemberPwdReset.setDescript(reason);
        memberPwdResetMapper.updateByPrimaryKeySelective(tSysMemberPwdReset);

    }

    @Override
    public SysUserInfoBaseVo getUserInfoBaseVoByUserId(Long userId) {
        SysUserInfoBaseVo sysUserInfoBaseVo = sysUserMapper.getUserInfoBaseVoByUserId(userId);
        if (sysUserInfoBaseVo == null) {
            throw ReqCode.UnExistingSysUser.getException();
        }
        return sysUserInfoBaseVo;
    }

    public void modifySysUserAdminLoginPerm(Long id) {
        if(id==1L){
            throw ReqCode.NoSupportChangeError.getException();
        }
        if(sysUserMapper.isAdmin(id)){
            sysUserMapper.removeAdminLoginPerm(id);
        }else{
            sysUserMapper.addAdminLoginPerm(id);
        }
    }


    @Override
    public Integer getTodayCheckIn(Long userId) {
        return memberCheckInMapper.getTodayCheckIn(userId,LocalDate.now().toDate());
    }

    @Transactional
    @Override
    public void memberCheckIn(Long userId) {
        /**
         * 1、今天是否已经签到过
         * 2、不可重复签到
         * 3、更新签到奖励详情
         * 4、更新账变记录
         * 5、更新账户积分
         */
        if(memberCheckInMapper.getTodayCheckIn(userId,LocalDate.now().toDate()).equals(Integer.valueOf(Constant.sysConfMap.get(Constant.KEY_CHECK_IN_COUNT)))){
            throw ReqCode.MemeberCheckInCompelete.getException();
        }
        //增加账户积分
        TSysMemberAsset asset = memberAssetMapper.selectByPrimaryKey(userId);
        Integer rewardNum = Integer.valueOf(Constant.sysConfMap.get(Constant.KEY_CHECK_IN_REWARD));
        asset.setBalance(asset.getBalance()+rewardNum);
        if(memberAssetMapper.updateByVersion(asset)!=1){
            throw ReqCode.DataLockedUpdateError.getException();
        }

        TSysMemberCheckInReward tSysMemberCheckInReward = new TSysMemberCheckInReward();
        //更新签到记录
        TSysMemberCheckIn tSysMemberCheckIn = new TSysMemberCheckIn();
        tSysMemberCheckIn.setCheckInDate(LocalDate.now().toDate());
        tSysMemberCheckIn.setUserId(userId);
        tSysMemberCheckIn.setCheckInDate(LocalDateTime.now().toDate());
        tSysMemberCheckIn.setUserName(SecurityUtils.getSubject().getSession().getAttribute(Constant.KEY_USER_USER_NAME).toString());
        memberCheckInMapper.insertSelective(tSysMemberCheckIn);

        //更新签到详情记录
        tSysMemberCheckInReward.setCheckInId(tSysMemberCheckIn.getId());
        tSysMemberCheckInReward.setCheckInRewardBalance(rewardNum);
        tSysMemberCheckInReward.setOperator("admin");
        tSysMemberCheckInReward.setOperatorIp("0.0.0.0");
        tSysMemberCheckInReward.setState(1);
        memberCheckInRewardMapper.insertSelective(tSysMemberCheckInReward);

        //更新账户积分账变记录
        TSysMemberAssetLog tSysMemberAssetLog = new TSysMemberAssetLog();
        tSysMemberAssetLog.setBalance(rewardNum);
        tSysMemberAssetLog.setAssetBalance(asset.getBalance());
        tSysMemberAssetLog.setAssetFreezeBalance(asset.getFreezeBalance());
        tSysMemberAssetLog.setType(AssetChangeCode.ADD_CHECK_IN.getType());
        tSysMemberAssetLog.setDescript(AssetChangeCode.ADD_CHECK_IN.getDescript());
        tSysMemberAssetLog.setOperatorIp("0.0.0.0");
        tSysMemberAssetLog.setOperator(SecurityUtils.getSubject().getSession().getAttribute(Constant.KEY_USER_USER_NAME).toString());
        tSysMemberAssetLog.setSerialNo(sid.nextShort());
        tSysMemberAssetLog.setUserId(userId);
        memberAssetLogMapper.insertSelective(tSysMemberAssetLog);
    }

    @Override
    public Page<MemberCheckInVo> findAllCheckInReward(FindPagingVo findPagingVo) {
        PagingUtil.start(findPagingVo);
        return memberCheckInMapper.findAllCheckInReward(PagingUtil.buildWhereSQLToString(findPagingVo.getFindParams()));
    }

    @Override
    @Transactional
    public String checkOpenCodeInfo(String code,HttpServletRequest request) {
        /**
         * 公众号账号体系   授权登陆实际上分为以下步骤
         * 1、根据code获取临时的access_token
         * 2、根据access_token拉取用户的基本信息 snsapi_userinfo
         * 3、根据snsapi_userinfo 检测是否已注册
         *      a、未注册-->走账号注册流程
         *      b、已注册
         * 4、返回用户的openid
         * 5、controller中直接走登陆流程
         */
//        System.out.println("拿到的code是"+code);
//        System.out.println("微信公众号授权开始");
        String json = HttpUtil.get(Constant.WXGZH_H5_CLIENT_AUTH_ACCESS_TOKEN_URL.replace("CODE", code).replace("APPID",Constant.WXGZH_APP_ID).replace("SECRET",Constant.WXGZH_APP_SECRET));
//        System.out.println("授权的临时access_token"+json);
        JSONObject jsonObject = JSONObject.parseObject(json);
        if(StringUtils.isNotBlank(jsonObject.getString("openid"))){//微信的scope始终都是snsapi_userinfo
//            System.out.println("获取成功");
            //先查系统中是否有这个用户
            BaseUser baseUser = permMapper.getUserByWXGZH(jsonObject.getString("openid"));
            if (baseUser==null){
                //没有的话 去获取授权用户的微信基本信息，建立自己的账号体系
                String s = HttpUtil.get(Constant.WXGZH_H5_CLIENT_AUTH_USER_INFO_URL.replace("ACCESS_TOKEN", jsonObject.getString("access_token")).replace("OPENID", jsonObject.getString("openid")));
//                System.out.println("获取的用户基本信息是"+s);
                try {
                    s = new String(s.getBytes("ISO-8859-1"),"UTF-8");
//                    System.out.println("解码后的用户信息是"+s);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                JSONObject info = JSONObject.parseObject(s);
                //新建用户账号
                SysUserAddReq sysUserAddReq = new SysUserAddReq();
                sysUserAddReq.setNickName(info.getString("nickname"));
                sysUserAddReq.setUserName(info.getString("openid"));
                sysUserAddReq.setPassword(MD5.encrypt(MD5.encrypt(info.getString("openid"))));
                addSysUserAccount(sysUserAddReq,request);
                //用户账号建立之后查询用户id
                TSysUser tmp = new TSysUser();
                tmp.setUserName(jsonObject.getString("openid"));
                tmp = sysUserMapper.selectOne(tmp);

                //新建用户的openid数据
                TSysUserOpen tSysUserOpen = new TSysUserOpen();
                tSysUserOpen.setUserId(Integer.valueOf(tmp.getId().toString()));
                tSysUserOpen.setWxGzhOpenId(jsonObject.getString("openid"));
                sysUserOpenMapper.insertSelective(tSysUserOpen);

                TSysUserInfo tSysUserInfo = sysUserInfoMapper.selectByPrimaryKey(tmp.getId());
                tSysUserInfo.setHeadImage(info.getString("headimgurl"));
                tSysUserInfo.setThumbNailImage(info.getString("headimgurl"));
                sysUserInfoMapper.updateByPrimaryKeySelective(tSysUserInfo);
            }
        }
//        System.out.println("微信公众号授权结束");
        return jsonObject.getString("openid");
    }
}
